import time

import grpc
import peewee

from search_order_srv.proto import order_pb2, order_pb2_grpc
from google.protobuf.empty_pb2 import Empty
from search_order_srv.model.models import Order, OrderImg, Category, OrderMathImg
from search_order_srv.utils.grpc_utils import response_fail
from loguru import logger
from search_order_srv.config import config
from search_order_srv.utils.cv_img import runAllImageSimilaryFun


# 通过感知度分析 自动匹配图片
@logger.catch
def order_math(order_id):
    print("------------ 开始订单自动匹配 ---------------")
    # 当有新订单是才进行匹配
    order_list = OrderImg.select().group_by(OrderImg.order_id)
    if order_id:
        order_list.where(OrderImg.order_id == order_id)
    img_list = []
    for item in order_list:
        img_list.append(item.img_url)

    if len(img_list) == 0:
        return True
    result_list = runAllImageSimilaryFun(img_list)
    for item in result_list:
        # 没匹配上
        if item['optimal'] == 0:
            continue
        # 通过图片查找订单
        try:
            order_img = OrderImg.get(OrderImg.img_url == item['img_url'])
            math_order_img = OrderImg.get(OrderImg.img_url == item['math_url'])
            order = Order.get(Order.id == order_img.order_id)
            math_order = Order.get(Order.id == math_order_img.order_id)
        except peewee.DoesNotExist:
            continue
        # 查找是否有匹配记录
        try:
            math_order_img = OrderMathImg.get(OrderMathImg.order_id == order_img.order_id, OrderMathImg.math_order_id == math_order.id)
            math_order_img.order_id = order.id
            math_order_img.math_order_id = math_order.id
            math_order_img.order_title = order.title
            math_order_img.math_order_title = math_order.title
            math_order_img.optimal = item['optimal']
            math_order_img.math_time = time.time() * 1000
            math_order_img.math_img_url = item['math_url']
            math_order_img.img_url = item['img_url']
        except peewee.DoesNotExist:
            math_order_img = OrderMathImg()
            math_order_img.order_id = order.id
            math_order_img.math_order_id = math_order.id
            math_order_img.order_title = order.title
            math_order_img.math_order_title = math_order.title
            math_order_img.optimal = item['optimal']
            math_order_img.math_time = time.time() * 1000
            math_order_img.math_img_url = item['math_url']
            math_order_img.img_url = item['img_url']
        math_order_img.save()
    print(f"-------------- 本次匹配结束 等待下一次匹配.... -------------- ")
    return True


if __name__ == '__main__':
    order_math()


# 生成订单号
def generate_order_sn(user_id):
    from random import Random
    order_sn = f'{time.strftime("%Y%m%d%H%M%S")}{user_id}{Random().randint(10, 99)}'
    return order_sn


# 生成返回UserInfoRsp对象
@logger.catch
def convert_order_to_rsp(order, img_url):
    rsp = order_pb2.OrderInfoRsp()
    rsp.id = order.id
    rsp.uid = order.uid
    rsp.type = order.type
    rsp.orderSn = order.order_sn
    rsp.status = order.status
    rsp.categoryId = order.category_id
    rsp.title = order.title
    try:
        rsp.categoryName = order.category_name
    except Exception:
        rsp.categoryName = ""
    rsp.imgUrl.extend(img_url)
    rsp.desc = order.desc
    if order.claim_address:
        rsp.claimAddress = order.claim_address
    if order.claim_name:
        rsp.claimName = order.claim_name
    if order.claim_mobile:
        rsp.claimMobile = order.claim_mobile
    rsp.about = order.about
    if order.check_time:
        rsp.checkTime = int(order.check_time)
    if order.claim_time:
        rsp.claimTime = int(order.claim_time)
    rsp.createTime = int(order.create_time)
    return rsp


@logger.catch
def convert_category_to_rsp(category):
    return order_pb2.CategoryInfoRsp(id=category.id, pid=category.pid, title=category.title, level=category.level)


class OrderServicer(order_pb2_grpc.OrderServicer):

    # 手动匹配
    @logger.catch
    def MathOrder(self, request, context):
        order_math(request.orderId)
        return Empty()


    # 匹配订单列表
    @logger.catch
    def GetMathOrderList(self, request: order_pb2.MathOrderRequest, context):
        rsp = order_pb2.MathOrderListResponse()
        math = OrderMathImg().select().order_by(OrderMathImg.optimal.desc())
        if request.title:
            math = math.where(OrderMathImg.order_title % f"%{request.title}%")
        if request.mathTitle:
            math = math.where(OrderMathImg.math_order_title == request.mathTitle)
        page = 1
        limit = 10
        if request.page:
            page = request.page
        if request.limit:
            limit = request.limit
        offset = (page - 1) * limit
        rsp.total = math.count()
        rsp.page = page
        rsp.limit - limit
        math = math.limit(limit).offset(offset)
        for item in math:
            info_rsp = order_pb2.MathOrderResponse()
            info_rsp.id = item.id
            info_rsp.OrderTitle = item.order_title
            info_rsp.OrderMathTitle = item.math_order_title
            info_rsp.OrderImgUrl = item.img_url
            info_rsp.OrderMathImgUrl = item.math_img_url
            info_rsp.mathTime = item.math_time
            info_rsp.optimal = item.optimal
            info_rsp.OrderId = item.order_id
            info_rsp.OrderMathId = item.math_order_id
            rsp.data.append(info_rsp)
        return rsp

    @logger.catch
    def GetOrderList(self, request: order_pb2.OrderRequest, context):
        rsp = order_pb2.OrderListRsp()

        order = Order().select(Order, Category.title.alias("category_name")).join(Category, peewee.JOIN.LEFT_OUTER,
                                                                                  on=(
                                                                                          Order.category_id == Category.id)).order_by(
            Order.create_time.desc())
        if request.uid:
            order = order.where(Order.uid == request.uid)
        if request.type and request is not 0:
            order = order.where(Order.type == request.type)
        if request.orderSn:
            order = order.where(Order.order_sn == request.orderSn)
        if request.status:
            order = order.where(Order.status == request.status)
        if request.categoryId:
            order = order.where(Order.category_id == request.categoryId)
        if request.title:
            order = order.where(Order.title % f"%{request.title}%")
        if request.claimName:
            order = order.where(Order.claim_name == request.claimName)
        if request.claimMobile:
            order = order.where(Order.claim_mobile == request.claimMobile)
        print(order)
        # TODO 时间筛选
        rsp.total = order.count()
        page = 1
        limit = 10
        if request.page:
            page = request.page
        if request.limit:
            limit = request.limit
        offset = (page - 1) * limit
        order = order.limit(limit).offset(offset)
        for item in order:
            img_url = OrderImg.select().where(item.id == OrderImg.order_id)
            list = []
            for img in img_url:
                list.append(img.img_url)
            rsp.data.append(convert_order_to_rsp(item, list))

        return rsp

    @logger.catch
    def GetOrderInfoById(self, request: order_pb2.OrderInfoRequest, context):
        try:
            order = Order().get(Order.id == request.id)
            order_img = OrderImg.select().where(OrderImg.order_id == order.id)
            url_list = []
            for item in order_img:
                url_list.append(item.img_url)
            return convert_order_to_rsp(order, url_list)
        except peewee.DoesNotExist:
            response_fail(context, grpc.StatusCode.NOT_FOUND, "订单不存在")
            return order_pb2.OrderInfoRsp()

    @logger.catch
    def UpdateOrder(self, request: order_pb2.OrderRequest, context):
        try:
            order = Order().get(Order.id == request.id)
            if request.status:
                order.status = request.status
            if request.title:
                order.title = request.title
            if request.about:
                order.about = request.about
            if request.categoryId:
                order.category_id = request.categoryId
            if request.claimName:
                order.claim_name = request.claimName
            if request.claimMobile:
                order.claim_mobile = request.claimMobile
            # TODO 修改图片
            order.save()
            return Empty()
        except peewee.DoesNotExist:
            response_fail(context, grpc.StatusCode.NOT_FOUND, "订单不存在")
            return Empty()
        except Exception as e:
            response_fail(context, grpc.StatusCode.INTERNAL, f"服务器异常：{str(e)}")
            return Empty()

    @logger.catch
    def CreateOrder(self, request: order_pb2.OrderRequest, context):
        with config.DB.atomic() as txn:
            try:
                order = Order()
                order.order_sn = generate_order_sn(request.uid)
                order.uid = request.uid
                order.type = request.type
                order.status = request.status
                order.category_id = request.categoryId
                order.title = request.title
                order.desc = request.desc
                order.about = request.about
                order.about = request.about
                order.save()

                img_list = []
                for url in request.imgUrl:
                    img_list.append(OrderImg(order_id=order.id, img_url=url))
                # 插入图片表
                OrderImg.bulk_create(img_list)
                return convert_order_to_rsp(order, request.imgUrl)
            except peewee.PeeweeException as e:
                txn.rollback()
                response_fail(context, grpc.StatusCode.INTERNAL, f"服务器异常：{str(e)}")
                return order_pb2.OrderInfoRsp()
            except Exception as e:
                txn.rollback()
                response_fail(context, grpc.StatusCode.INTERNAL, f"内部异常：{str(e)}")
                return order_pb2.OrderInfoRsp()

    def DeleteOrder(self, request: order_pb2.OrderRequest, context):
        try:
            order = Order().get(Order.id == request.id)
            order.soft_delete()
            OrderImg.delete().where(OrderImg.order_id == request.id).execute()
            return Empty()
        except peewee.DoesNotExist:
            response_fail(context, grpc.StatusCode.NOT_FOUND, "订单不存在")
            return Empty()
        except peewee.PeeweeException as e:
            response_fail(context, grpc.StatusCode.INTERNAL, f"服务器异常：{str(e)}")
            return Empty()

    def CheckClaim(self, request: order_pb2.OrderRequest, context):
        try:
            order = Order().get(Order.id == request.id)
            if order.status != 0:
                response_fail(context, grpc.StatusCode.INTERNAL, "订单状态异常")
                return Empty()
            order.about = request.about
            order.check_time = int(time.time() * 1000)
            order.status = request.status
            order.save()
            return Empty()
        except peewee.DoesNotExist:
            response_fail(context, grpc.StatusCode.NOT_FOUND, "订单不存在")
            return Empty()
        except Exception as e:
            response_fail(context, grpc.StatusCode.INTERNAL, f"服务器异常：{str(e)}")
            return Empty()

    def ClaimOrder(self, request: order_pb2.OrderRequest, context):
        try:
            order = Order().get(Order.id == request.id)
            if order.status != 1:
                response_fail(context, grpc.StatusCode.INTERNAL, "订单状态异常")
                return Empty()
            order.claim_name = request.claimName
            order.claim_mobile = request.claimMobile
            order.claim_address = request.claimAddress
            order.about = request.about
            order.claim_time = int(time.time() * 1000)
            order.status = 2
            order.save()
            return Empty()
        except peewee.DoesNotExist:
            response_fail(context, grpc.StatusCode.NOT_FOUND, "订单不存在")
            return Empty()
        except Exception as e:
            response_fail(context, grpc.StatusCode.INTERNAL, f"服务器异常：{str(e)}")
            return Empty()

    @logger.catch
    def GetCategoryList(self, request: order_pb2.CategoryRequest, context):
        rsp = order_pb2.CategoryListRsp()

        category = Category().select()

        if request.pid:
            category.where(Category.pid == request.pid)
        if request.title:
            category.where(Category.title == request.title)
        if request.pid:
            category.where(Category.level == request.level)

        rsp.total = category.count()
        page = 1
        limit = 10
        if request.page:
            page = request.page
        if request.limit:
            limit = request.limit
        offset = (page - 1) * limit
        category = category.limit(limit).offset(offset)
        for item in category:
            rsp.data.append(convert_category_to_rsp(item))
        return rsp

    @logger.catch
    def GetCategoryById(self, request: order_pb2.CategoryRequest, context):
        try:
            category = Category().get(Category.id == request.id)
            return convert_category_to_rsp(category)
        except peewee.DoesNotExist:
            response_fail(context, grpc.StatusCode.NOT_FOUND, "订单不存在")
            return order_pb2.CategoryInfoRsp()

    @logger.catch
    def CreateCategory(self, request: order_pb2.CategoryRequest, context):
        category = Category()
        category.pid = request.pid
        category.title = request.title
        category.level = request.level
        category.save()
        return convert_category_to_rsp(category)

    @logger.catch
    def UpdateCategory(self, request: order_pb2.CategoryRequest, context):
        try:
            category = Category().get(Category.id == request.id)
            if request.pid:
                category.pid = request.pid
            if request.title:
                category.title = request.title
            if request.level:
                category.level = request.level
            category.save()
            return Empty()
        except peewee.DoesNotExist:
            response_fail(context, grpc.StatusCode.NOT_FOUND, "分类不存在")
            return Empty()
        except peewee.PeeweeException as e:
            response_fail(context, grpc.StatusCode.INTERNAL, "服务器异常")
            return Empty()

    @logger.catch
    def DeleteCategory(self, request: order_pb2.CategoryRequest, context):
        try:
            category = Category().get(Category.id == request.id)
            category.soft_delete()
            return Empty()
        except peewee.DoesNotExist:
            response_fail(context, grpc.StatusCode.NOT_FOUND, "分类不存在")
            return Empty()
